package com.ruoyi.generator.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.GenConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysDictType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.generator.domain.*;
import com.ruoyi.generator.mapper.FromBuildConfigMapper;
import com.ruoyi.generator.mapper.FromBuildOptionsConfigMapper;
import com.ruoyi.generator.mapper.FromBuildRuleConfigMapper;
import com.ruoyi.generator.mapper.GenTableColumnMapper;
import com.ruoyi.generator.service.IFromBuildConfigService;
import com.ruoyi.generator.service.IGenTableService;
import com.ruoyi.generator.util.GenUtils;
import com.ruoyi.generator.util.ModuleReqPrefixUtil;
import com.ruoyi.system.mapper.SysDictTypeMapper;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 单设计_配置Service业务层处理
 *
 * @author XL
 * @date 2022-08-05 12:01:23
 */
@Service
public class FromBuildConfigServiceImpl implements IFromBuildConfigService {
    @Autowired
    private FromBuildConfigMapper fromBuildConfigMapper;

    @Autowired
    private SysDictTypeMapper dictTypeMapper;

    @Autowired
    private ISysDictDataService dictDataService;

    /**
     * 删除校验规则
     */
    @Autowired
    private FromBuildRuleConfigMapper fromBuildRuleConfigMapper;

    /**
     * 删除下拉选项
     */
    @Autowired
    private FromBuildOptionsConfigMapper fromBuildOptionsConfigMapper;

    @Autowired
    private GenTableColumnMapper genTableColumnMapper;

    @Autowired
    private IGenTableService iGenTableService;

    @Autowired
    private ISysDictTypeService dictTypeService;

    /**
     * 查询单设计_配置
     *
     * @param id 单设计_配置ID
     * @return 单设计_配置
     */
    @Override
    public FromBuildConfig selectFromBuildConfigById(Long id) {
        return fromBuildConfigMapper.selectFromBuildConfigById(id);
    }

    /**
     * 查询单设计_配置列表
     *
     * @param fromBuildConfig 单设计_配置
     * @return 单设计_配置
     */
    @Override
    public List<FromBuildConfig> selectFromBuildConfigList(FromBuildConfig fromBuildConfig) {
        return fromBuildConfigMapper.selectFromBuildConfigList(fromBuildConfig);
    }

    /**
     * 新增单设计_配置
     *
     * @param fromBuildConfig 单设计_配置
     * @return 结果
     */
    @Override
    public int insertFromBuildConfig(FromBuildConfig fromBuildConfig) {
        return fromBuildConfigMapper.insertFromBuildConfig(fromBuildConfig);
    }

    /**
     * 修改单设计_配置
     *
     * @param fromBuildConfig 单设计_配置
     * @return 结果
     */
    @Override
    public int updateFromBuildConfig(FromBuildConfig fromBuildConfig) {
        return fromBuildConfigMapper.updateFromBuildConfig(fromBuildConfig);
    }

    /**
     * 批量删除单设计_配置
     *
     * @param ids 需要删除的单设计_配置ID
     * @return 结果
     */
    @Override
    public int deleteFromBuildConfigByIds(Long[] ids) {
        return fromBuildConfigMapper.deleteFromBuildConfigByIds(ids);
    }

    /**
     * 删除单设计_配置信息
     *
     * @param id 单设计_配置ID
     * @return 结果
     */
    @Override
    public int deleteFromBuildConfigById(Long id) {
        return fromBuildConfigMapper.deleteFromBuildConfigById(id);
    }

    /**
     * ==================================================================================================
     */

    /**
     * 获取表单设计字段配置信息
     */
    @Override
    public List<FromBuildConfig> getFormBuildConfig(String formBuildKey, String clientType) {

        List<FromBuildConfig> formBuildConfigs = fromBuildConfigMapper.getFormBuildConfig(formBuildKey, clientType);

        /** 处理特殊的参数，如字符串转成对象 **/
        formBuildConfigs = dealSpecialParam(formBuildConfigs);

        return formBuildConfigs;
    }

    /**
     * 根据业务表模块名，获取对应所有的表单设计KEY
     * @param businessName
     * @return
     */
    @Override
    public List<Map<String,Object>> getAllFormBuildKeyByBusinessName(String businessName){
        return fromBuildConfigMapper.getAllFormBuildKeyByBusinessName(businessName);
    }

    /**
     * 处理特殊的参数，如字符串转成对象
     * @param configs
     * @return
     */
    private List<FromBuildConfig> dealSpecialParam(List<FromBuildConfig> configs){
        try{
            for(FromBuildConfig item:configs){

                if(item.getChildren()!=null && item.getChildren().size()>0){
                    item.setChildren(dealSpecialParam(item.getChildren()));
                }

                if(!"textarea".equals(item.getModuleType().toLowerCase())){
                    continue;
                }
                if(item.getAutosize() !=null){
                    item.setAutosize(JSONObject.parseObject(String.valueOf(item.getAutosize())));
                }else{
                    item.setAutosize(JSONObject.parseObject("{\"minRows\":4,\"maxRows\":4}"));
                }
            }
        }catch (Exception e){ }
        return configs;
    }

    public List<Map<String, String>> getTableGenInfo(String formBuildKey) {

        return fromBuildConfigMapper.getTableGenInfo(formBuildKey);
    }

    /**
     * 特殊参数处理
     */
    public void paramDeal(List<FromBuildConfig> formBuildConfigInfoList) {

        for(FromBuildConfig item:formBuildConfigInfoList){
            //Style样式
            if(item.getStyle() !=null){
                try{
                    item.setStyle(JSONObject.parseObject(String.valueOf(item.getStyle())));
                }catch (Exception e){ }
            }
            //多行文本框
            if("textarea".equals(item.getModuleType().toLowerCase())) {
                try {
                    item.setAutosize(JSONObject.parseObject(String.valueOf(item.getAutosize())));
                } catch (Exception e) {
                    item.setAutosize(JSONObject.parseObject("{\"minRows\":4,\"maxRows\":4}"));
                }
            }
        }
    }

    /**
     * 特殊参数处理
     */
    private void paramDeal(JSONObject obj) throws Exception {
        obj.put("prefixIcon", obj.get("prefix-icon"));
        obj.remove("prefix-icon");
        obj.put("suffixIcon", obj.get("suffix-icon"));
        obj.remove("suffix-icon");
        obj.put("showWordLimit", obj.get("show-word-limit"));
        obj.remove("show-word-limit");
        obj.put("activeValue", obj.get("active-value"));
        obj.remove("active-value");
        obj.put("inactiveValue", obj.get("inactive-value"));
        obj.remove("inactive-value");
        /**
         * 样式
         */
        obj.remove("style");
        /**
         * 校验规则
         */
        obj.remove("regList");
        /**
         * 子组件
         */
        obj.remove("children");
    }

    /**
     * 处理流程节点信息
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult saveFormInfo(Long tableId,String formBuildKey, String clientType, List<FromBuildConfig> fromBuildConfigs) throws Exception {

        if (StringUtils.isEmptyIncludeNull(formBuildKey)) {
            return AjaxResult.error("表单设计编码不能为空");
        }
        /**
         * 删除校验规则
         */
        fromBuildRuleConfigMapper.deleteFormRuleConfigByBuildKey(formBuildKey, clientType);
        /**
         * 删除下拉选项
         */
        fromBuildOptionsConfigMapper.deleteFromBuildOptionsConfigByBuildKey(formBuildKey, clientType);
        /**
         * 删除表单配置
         */
        fromBuildConfigMapper.deleteFromBuildConfigByBuildKey(formBuildKey, clientType);

        if(fromBuildConfigs==null){
            return AjaxResult.success();
        }

        for (int i = 0; i < fromBuildConfigs.size(); i++) {
            FromBuildConfig fromBuildConfig = fromBuildConfigs.get(i);
            /**
             * 显示顺序
             */
            fromBuildConfig.setSort(i + 1);
            /**
             * 显示层级
             */
            fromBuildConfig.setGrade(1);
            /**
             * 终端类型__PC_Mobile
             */
            fromBuildConfig.setClientType(clientType);
            /**
             * 处理表单信息
             */
            this.dealFormItem(tableId,formBuildKey, null, fromBuildConfig);
        }

        return AjaxResult.success();
    }

    /**
     * 处理表单组件
     */
    private void dealFormItem(Long tableId,String formBuildKey, FromBuildConfig parent, FromBuildConfig fromBuildConfig) throws Exception {
        /**
         * 校验规则
         */
        List<FromBuildRuleConfig> regList = fromBuildConfig.getRegList();
        /**
         * 选项值
         */
        List<FromBuildOptionsConfig> options = fromBuildConfig.getOptions();
        /**
         * 子组件
         */
        List<FromBuildConfig> children = fromBuildConfig.getChildren();

        /**
         * 设置流程编码
         */
        fromBuildConfig.setBuildKey(formBuildKey);
        /**
         * 设置表单组件UUID
         */
        fromBuildConfig.setFormUuid(GenUtils.getUUID());
        if(StringUtils.isEmptyIncludeNull(fromBuildConfig.getFormId())){
            fromBuildConfig.setFormId(fromBuildConfig.getFormUuid());
        }
        /**
         * 将父组件的一些属性同步更新到子组件
         */
        if (parent != null) {
            /**
             * 设置表单父组件UUID
             */
            fromBuildConfig.setParentFormUuid(parent.getFormUuid());
        }
        /**
         * 判断是否存在子组件
         */
        fromBuildConfig.setHasChildren("0");
        if (children != null && children.size() >= 0) {
            fromBuildConfig.setHasChildren("1");
            this.dealFormItemChild(tableId,formBuildKey, fromBuildConfig, children);
        }
        /**
         * 处理校验规则
         */
        if (regList != null && regList.size() > 0) {
            for (int i = 0; i < regList.size(); i++) {
                FromBuildRuleConfig fromBuildRuleConfig = regList.get(i);
                /**
                 * 设置流程节点编码
                 */
                fromBuildRuleConfig.setBuildKey(formBuildKey);
                fromBuildRuleConfig.setFormUuid(fromBuildConfig.getFormUuid());
                fromBuildRuleConfig.setSort(i + 1);
                fromBuildRuleConfig.setClientType(fromBuildConfig.getClientType());
                fromBuildRuleConfigMapper.insertFromBuildRuleConfig(fromBuildRuleConfig);
            }
        }
        /**
         * 处理选项值
         */
        if (options != null && options.size() > 0) {
            for (int i = 0; i < options.size(); i++) {
                FromBuildOptionsConfig fromBuildOptionsConfig = options.get(i);
                /**
                 * 设置流程节点编码
                 */
                fromBuildOptionsConfig.setBuildKey(formBuildKey);
                fromBuildOptionsConfig.setFormUuid(fromBuildConfig.getFormUuid());
                fromBuildOptionsConfig.setSort(i + 1);
                fromBuildOptionsConfig.setClientType(fromBuildConfig.getClientType());
                fromBuildOptionsConfigMapper.insertFromBuildOptionsConfig(fromBuildOptionsConfig);

            }
            //同步更新字典项
            if(StringUtils.isNotEmptyIncludeNull(fromBuildConfig.getOptionDictCode())){
                syncSysDict(fromBuildConfig.getOptionDictCode(),options );
            }
        }
        /**
         * 判断当前组件是否是子表，如果是子表则需要获取出对应全类名
         */
        if (StringUtils.isNotEmpty(fromBuildConfig.getModuleType())  && (
                "ElTable".equals(fromBuildConfig.getModuleType())
                || "ElFileUpload".equals(fromBuildConfig.getModuleType()))) {
            List<Map<String, String>> tableGenInfo = fromBuildConfigMapper.getTableGenInfo(fromBuildConfig.getVModel());
            if (tableGenInfo.size() > 0) {
                //服务实现全类名
                fromBuildConfig.setServiceName(StringUtils.format("{}.service.impl.{}ServiceImpl", tableGenInfo.get(0).get("packageName"), tableGenInfo.get(0).get("businessName")));
                /**
                 * 子表接口请求前缀，可能是平台标准方式，也可能是优树搭方式
                 */
                Map<String,String> prefixUrlInfo=new HashMap<>();
                //0zip压缩包 1自定义路径 2优树搭
                prefixUrlInfo.put("genType",tableGenInfo.get(0).get("genType"));
                //业务表生成ID
                String _tableId = fromBuildConfig.getBindMenu();
                if(StringUtils.isEmptyIncludeNull(_tableId)){
                    _tableId=String.valueOf(tableGenInfo.get(0).get("tableId"));
                }
                prefixUrlInfo.put("tableId",_tableId);
                //平台标准方式的访问前缀
                String baseUrl = StringUtils.format("/{}", tableGenInfo.get(0).get("businessName"));
                if(StringUtils.isNotEmptyIncludeNull(tableGenInfo.get(0).get("moduleName"))){
                    baseUrl = StringUtils.format("/{}/{}", ModuleReqPrefixUtil.getModuleRequestPrefix(tableGenInfo.get(0).get("moduleName")), tableGenInfo.get(0).get("businessName"));
                }
                prefixUrlInfo.put("baseUrlPrefix",baseUrl);
                fromBuildConfig.setPrefixUrl(JSONObject.toJSONString(prefixUrlInfo));
            }
        }
        Object defaultValue = fromBuildConfig.getDefaultValue();
        if(defaultValue instanceof List){
            List defaultValues= (List) defaultValue;
            fromBuildConfig.setDefaultValue(String.join(",", defaultValues));
        }
        /**
         * 特殊参数处理
         */
        dealSpecialParams(fromBuildConfig);
        /**
         * 保存表单配置信息
         */
        fromBuildConfigMapper.insertFromBuildConfig(fromBuildConfig);
        /**
         * 修改对应字段配置信息
         */
        if(tableId!=null){
            try{
                /** 当配置表单时，未对组件进行对应字段关联时，修改数据库字段会异常 **/
                genTableColumnMapper.updateGenTableColumnByJavaField(genNeedUpdateTableColumnInfo(tableId,fromBuildConfig));
            }catch (Exception e){}
        }
    }


    /**
     * 同步更新字典项
     * @param dictType
     * @param options
     */
    private void syncSysDict(String dictType,List<FromBuildOptionsConfig> options ){
        if(StringUtils.isEmptyIncludeNull(dictType) || options == null || options.size()<=0){
            return;
        }
        dictType = dictType.toLowerCase();
        /**
         * 字典信息
         */
        SysDictType dict = dictTypeMapper.checkDictTypeUnique(dictType);
        if (dict == null){
            return;
        }
        //删除之前字典信息
        dictDataService.deleteDictDataByDictType(dictType);
        /**
         * 选项信息
         */
        for (int i = 0; i < options.size(); i++) {
            FromBuildOptionsConfig fromBuildOptionsConfig = options.get(i);
            SysDictData _dict = new SysDictData();
            //字典类型
            _dict.setDictType(dictType);
            //数据标签
            _dict.setDictLabel(fromBuildOptionsConfig.getLabel());
            //数据键值
            _dict.setDictValue(fromBuildOptionsConfig.getValue());
            //显示排序
            _dict.setDictSort((long) i);
            //状态
            _dict.setStatus("0");
            dictDataService.insertDictData(_dict);
        }
    }

    /**
     * 特殊参数处理
     * @param fromBuildConfig
     */
    private void dealSpecialParams(FromBuildConfig fromBuildConfig){
        //多行文本的最小行数与最大行数
        if(fromBuildConfig.getAutosize()!=null){
            fromBuildConfig.setAutosize(JSONObject.toJSONString(fromBuildConfig.getAutosize()));
        }
        //样式处理
        if(fromBuildConfig.getStyle()!=null){
            if(!"java.lang.String".equals(fromBuildConfig.getStyle().getClass().getTypeName())){
                fromBuildConfig.setStyle(JSONObject.toJSONString(fromBuildConfig.getStyle()));
            }
        }
    }

    /**
     * 处理组件对应子组件
     */
    private void dealFormItemChild(Long tableId,String formBuildKey, FromBuildConfig parent, List<FromBuildConfig> children) throws Exception {

        for (int i = 0; i < children.size(); i++) {
            FromBuildConfig fromBuildConfig = children.get(i);
            /**
             * 显示顺序
             */
            fromBuildConfig.setSort(i + 1);
            /**
             * 显示层级
             */
            fromBuildConfig.setGrade(2);
            /**
             * 终端类型__PC_Mobile
             */
            fromBuildConfig.setClientType(parent.getClientType());

            this.dealFormItem(tableId,formBuildKey, parent, fromBuildConfig);

        }
    }

    /**
     * 获取需要修改的字段信息
     * @param fromBuildConfig
     * @return
     */
    private GenTableColumn genNeedUpdateTableColumnInfo(Long tableId,FromBuildConfig fromBuildConfig){
        GenTableColumn genTableColumn=new GenTableColumn();
        /** 归属表编号 */
        genTableColumn.setTableId(tableId);
        /** JAVA字段名 */
        genTableColumn.setJavaField(fromBuildConfig.getVModel());
        /** 字典类型 */
        genTableColumn.setDictType(fromBuildConfig.getOptionDictCode());
        /** 搜索表名__针对搜索文本框时的配置 **/
        genTableColumn.setSearchModel(fromBuildConfig.getSearchModel());
        /** 同步控件类型 **/
        genTableColumn.setHtmlType(fromBuildConfig.getModuleType());
//        /** 中文字段名 */
//        genTableColumn.setColumnComment(fromBuildConfig.getLabel());
//        /** 是否列表字段（1是） */
//        genTableColumn.setIsList(getGenTableColumnBoolStr(fromBuildConfig.getIsListShow()));
//        /** 列表宽度 */
//        if(StringUtils.isNotEmptyIncludeNull(fromBuildConfig.getListColumnWidth())){
//            genTableColumn.setColumnWidth(Integer.parseInt(fromBuildConfig.getListColumnWidth()));
//        }
//        /** 列表对齐方式 */
//        genTableColumn.setColumnAlign(fromBuildConfig.getListColumnAlign());
//        /** 是否查询字段（1是） */
//        genTableColumn.setIsQuery(getGenTableColumnBoolStr(fromBuildConfig.getIsQuery()));
//        /** 查询方式（EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围） */
//        genTableColumn.setQueryType(fromBuildConfig.getQueryType());

        return genTableColumn;
    }

    /**
     * 转换成gen_table_column表中的bool表达
     * @param bool
     * @return
     */
    private String getGenTableColumnBoolStr(String bool){
        if(StringUtils.isEmptyIncludeNull(bool)){
            return "0";
        }
        return "true".equals(bool.toLowerCase())?"1":"0";
    }

    /**
     * 根据业务表生成ID获取对应表配置信息
     * @param menuTabId
     * @return
     */
    @Override
    public GenTableConfig getGenTableConfig(String menuTabId){
        if(StringUtils.isEmptyIncludeNull(menuTabId)){
            return null;
        }
        String[] menuTabIdInfo = menuTabId.split("_");
        GenTableConfig genConfig = null;
        if(menuTabIdInfo.length == 1){
            genConfig = iGenTableService.getGenConfigByTableId(Long.valueOf(menuTabIdInfo[0]));
        }else{
            genConfig = iGenTableService.getGenConfigByMenuId(Long.valueOf(menuTabIdInfo[1]));
        }
        return genConfig;
    }

    /**
     * 根据业务表生成ID获取对应表字段配置信息
     * @return
     */
    @Override
    public Map<String,Map> getGenTableColumnConfig(Long tableId){
        return genTableColumnMapper.getGenTableColumnConfig(tableId);
    }

    /**
     * 根据菜单配置获取对应表配置信息
     * @param menuTabId
     * @return
     */
    @Override
    public GenTableConfig getGenTableConfigIncludeColumn(String menuTabId){
        return getGenTableConfigIncludeColumn(menuTabId,true);

    }

    @Override
    public GenTableConfig getGenTableConfigIncludeColumn(String menuTabId,boolean columnNameIsCamel){
        /**
         * 由  业务表ID_菜单ID 组成
         */
        if(StringUtils.isEmptyIncludeNull(menuTabId)){
            return null;
        }
        String[] menuTabIdInfo = menuTabId.split("_");
        GenTableConfig genConfig = null;
        if(menuTabIdInfo.length == 1){
            genConfig = iGenTableService.getGenConfigByTableId(Long.valueOf(menuTabIdInfo[0]));
        }else{
            genConfig = iGenTableService.getGenConfigByMenuId(Long.valueOf(menuTabIdInfo[1]));
        }
        if(genConfig==null){
            return null;
        }
        String perms = genConfig.getPerms();
        if(StringUtils.isNotEmptyIncludeNull(perms) && perms.indexOf(":")>-1){
            perms=perms.substring(0,perms.lastIndexOf(":"));
            genConfig.setPerms(perms);
        }

        /**
         * 获取业务表配置字段信息
         */
        List<GenTableColumn> fieldInfos = null;
        try {
            fieldInfos = getFieldInfoByTabName(genConfig.getTableName(),columnNameIsCamel);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        genConfig.setFieldInfos(fieldInfos);

        return genConfig;

    }



    /**
     * 根据表名获取对应字段配置信息
     * @param tabName
     * @return
     */
    @Override
    public AjaxResult getColumnConfigByTableName(String tabName){
        return getColumnConfigByTableName(tabName,true);
    }

    public AjaxResult getColumnConfigByTableName(String tabName,boolean columnNameIsCamel){
        try {
            GenTableConfig genTableConfig = new GenTableConfig();
            genTableConfig.setFieldInfos(getFieldInfoByTabName(tabName,columnNameIsCamel));
            return AjaxResult.success(genTableConfig);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取业务表生成字段信息异常");
        }
    }

    /**
     * 根据表名获取对应字段信息
     * @param tabName
     * @param columnNameIsCamel  字段名是否需要驼峰格式
     * @return
     */
    private List<GenTableColumn> getFieldInfoByTabName(String tabName,boolean columnNameIsCamel){
        List<GenTableColumn> fieldInfo = iGenTableService.getFieldByTabName(tabName,columnNameIsCamel);
        for (GenTableColumn columnConfig : fieldInfo) {
            if (StringUtils.isNotEmpty(columnConfig.getDictType())
                    && Arrays.asList("select","multipleSelect","allowCreateSelect","multipleallowCreateSelect","radio","checkbox").contains(columnConfig.getHtmlType())) {
                columnConfig.setDictItems(dictTypeService.selectDictDataByType(columnConfig.getDictType()));
            }
            //字段长度
            columnConfig.setColumnLength(getColumnLength(columnConfig.getColumnType()));
        }
        return fieldInfo;
    }

    /**
     * 获取字段长度
     *
     * @param columnType 列类型
     * @return 截取后的列类型
     */
    private Integer getColumnLength(String columnType)
    {
        try{
            if (StringUtils.indexOf(columnType, "(") > 0)
            {
                String length = StringUtils.substringBetween(columnType, "(", ")");
                if(length.indexOf(",")>-1){
                    //有可能存在保留小位的情况
                    String[] _lengths = length.split(",");
                    return Integer.valueOf(_lengths[0]);
                }
                return Integer.valueOf(length);
            }
            else
            {
                return 0;
            }
        }catch (Exception e){
            return 0;
        }
    }
}
